/* Copyright (c) 2008, Nozomi SATO. All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 
 *  1. Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *  2. Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *  3. Neither the name of Nozomi Sato nor the names of its contributors
 *     may be used to endorse or promote products derived from this
 *     software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
 * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */


#define R_INDEX		2
#define G_INDEX		1
#define B_INDEX		0

#define GET_R(x)	x[R_INDEX]
#define GET_G(x)	x[G_INDEX]
#define GET_B(x)	x[B_INDEX]

#define RGB_BPP		3

#define PRECISION_SHIFT	8
#define PRECISION_VALUE	(1 << PRECISION_SHIFT)

@ r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 r11 r12 r13 r14 r15
@ r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 sl  fp  ip  sp  lr  pc

#define	pDst	r0
#define x		r1
#define pWVectors	r2
#define u		r3
#define u_opposite r3
#define v		r4
#define v_opposite r4
#define p0		r5
#define p1		r6
#define p2		r7
#define p3		r8
#define pLine0	r9
#define pLine1	r10
#define t1		r11
#define t2		r12
#define t3		r14

#define FUNC_NAME	doBilinearLine_BGR888

#define STACK_VARS	3

@ void doBilinearLine(u8 *pDst, s32 dstWidth, s32 *pWVectors, u8 *pHSamples[], s16 *pU, s32 v)
	.text
	.align 2
	.global	FUNC_NAME
FUNC_NAME:
	stmfd	sp!, {r4, r5, r6, r7, r8, r9, r10, r11, r14}
	sub		sp, sp, #STACK_VARS * 4
	str		r1,	[sp, #4]			@ dstWidth
	mov		t2, r1					@ t2 = t1

	ldr		r14, [sp, #(STACK_VARS * 4 + 36)] @ pU
	mov		r1,  #0					@ x = 0
	str		r14, [sp, #8]			@ save pU

	ldr		pLine0, [r3, #0]		@ pLine0 = pHSamples[0]

	ldr		r4,	[sp, #(STACK_VARS * 4 + 36 + 4)] @ v
	ldr		pLine1, [r3, #4]		@ pLine0 = pHSamples[1]
#if (PRECISION_SHIFT <= 6)
	rsb		r3,	r4, #PRECISION_VALUE	@ PRECISION_VALUE - v
	orr		r4, r3, lsl #16			@ v |= v_opposite << 16
#endif
	nop
	nop
.L0:
	cmp		x, t2
	blt		.L1						@ x < t2 && goto L1

	add		sp, sp, #STACK_VARS * 4
	ldmia	sp!, {r4, r5, r6, r7, r8, r9, r10, r11, pc}
.L1:
	ldr		t2,	[sp, #8]			@ t2 = pU
	lsl		t1, x, #1				@ t1 = x << 1
	ldrsh	u, [t2, t1]				@ u = pU[x]
	ldr		t2, [pWVectors, #0]		@ t2 = pWVectors[0]
#if (RGB_BPP != 4)
	mov		t3, #RGB_BPP
#endif
	rsb		t1, u, #PRECISION_VALUE	@ PRECISION_VALUE - u
	orr		u, t1, lsl #16			@ u |= opposite_u << 16

#if (RGB_BPP == 4)
	add		p0, pLine0, t2, lsl #2
	ldr		t1, [pWVectors, #4]
	add		p2, pLine1, t2, lsl #2
	add		p1, pLine0, t1, lsl #2
	add		p3, pLine1, t1, lsl #2
#else
	mla		p0, t2, t3, pLine0		@ p0 = pWVectors[0] * RGB_BPP + pLine0

	ldr		t1, [pWVectors, #4]
	mla		p2, t2, t3, pLine1		@ p1 = pWVectors[0] * RGB_BPP + pLine1
	mla		p1, t1, t3, pLine0		@ p1 = pWVectors[1] * RGB_BPP + pLine0
	mla		p3, t1, t3, pLine1		@ p3 = pWVectors[1] * RGB_BPP + pLine1 
#endif

.L2:
	@ (y0(1-U) + y1U) * (1-V)) + ((y2(1-U) + y3U) * V)
	.macro  set_one, index
	ldrb	t1, [p0, #\index]		@ t1  = p0[index]
	ldrb	t3, [p1, #\index]		@ t3  = p1[index]
	smulbt	t2, t1, u				@ t2  = t1 * opposite_u
	smlabb	t2, t3, u, t2			@ t2 += t3 * u
#if (PRECISION_SHIFT <= 6)
	ldrb	t1, [p2, #\index]		@ t1  = p2[index]
	smulbt	t3, t2, v				@ t3  = t2 * opposite_v
#else
	rsb		t1, v, #PRECISION_VALUE
	mul		t3, t2, t1				@ t3  = t2 * opposite_y
	ldrb	t1, [p2, #\index]		@ t1  = p2[index]
#endif

	smulbt	t2, t1, u				@ t2  = t1 * opposite_u
	ldrb	t1, [p3, #\index]		@ t1  = p3[index]
	smlabb	t2, t1, u, t2			@ t2 += t1 * u
#if (PRECISION_SHIFT <= 6)
	smlabb  t1, t2, v, t3			@ t1  = t2 * v + t3
#else
	mla		t1, t2, v, t3			@ t1  = t2 * v + t3
#endif

	lsr		t1, #PRECISION_SHIFT * 2 @ t1 >>= PRECISION_INDEX * 2
	strb	t1, [pDst, #\index]		@ pDst[R_INDEX] = t1
	.endm

	set_one	R_INDEX

	set_one G_INDEX

	set_one B_INDEX

.L128:
	add		pDst, #RGB_BPP			@ pDst += 3
	add		pWVectors, #2 * 4		@ pWVectors += 2
	ldr		t2, [sp, #4]			@ t2 = dstWidth
	add		x, x, #1				@ x++
	b		.L0
	
